#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
#include <string.h>
#include <unistd.h>
#include <vector>
#include <map>
#include <iostream>
#include "plugin/CPluginController.h"
#include <stdlib.h>
#include <string>
#include <sstream>
#include <pthread.h>

using namespace std;

// 最大线程数量
#define MAX_CONN 100 

class CMyTCPServer;

// 线程传递的数据结构
typedef struct 
{
	CMyTCPServer* server;
	int nConnectedSocket;

}Thread_data;


// 线程操作函数
void* serverFun( void* arg );

template <typename ConnectionProcessor>
class CTCPServer : public ConnectionProcessor
{
public:
	CTCPServer(int nServerPort, int nLengthOfQueueOfListen = 100, const char *strBoundIP = NULL)
	{
		m_nServerPort = nServerPort;
		m_nLengthOfQueueOfListen = nLengthOfQueueOfListen;

		if (NULL == strBoundIP)
		{
			m_strBoundIP = NULL;
		}
		else
		{
			int length = strlen(strBoundIP);
			m_strBoundIP = new char[length + 1];
			memcpy(m_strBoundIP, strBoundIP, length + 1);
		}
	}

	virtual ~CTCPServer()
	{
		if (m_strBoundIP != NULL)
		{
			delete[] m_strBoundIP;
		}
	}

public:
	int Run()
	{
		std::cout << "enter run" << std::endl;
		int nListenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
		if (-1 == nListenSocket)
		{
			std::cout << "socket error" << std::endl;
			return -1;
		}
		std::cout << "socket" << std::endl;
		sockaddr_in ServerAddress;
		memset(&ServerAddress, 0, sizeof(sockaddr_in));
		ServerAddress.sin_family = AF_INET;

		if (NULL == m_strBoundIP)
		{
			ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
		}
		else
		{
			if (::inet_pton(AF_INET, m_strBoundIP, &ServerAddress.sin_addr) != 1)
			{
				std::cout << "inet_pton error" << std::endl;
				::close(nListenSocket);
				return -1;
			}
		}

		ServerAddress.sin_port = htons(m_nServerPort);
		std::cout << "ip port" << std::endl;

		if (::bind(nListenSocket, (sockaddr *)&ServerAddress, sizeof(sockaddr_in)) == -1)
		{
			std::cout << "bind error" << std::endl;
			::close(nListenSocket);
			return -1;
		}

		if (::listen(nListenSocket, m_nLengthOfQueueOfListen) == -1)
		{
			std::cout << "listen error" << std::endl;
			::close(nListenSocket);
			return -1;
		}
		std::cout << "bing listen" << std::endl;
		sockaddr_in ClientAddress;
		socklen_t LengthOfClientAddress = sizeof(sockaddr_in);

		int i=0;
		int nConnectedSocket;
		bool breakbool = true;
		pthread_t tid;
		Thread_data thread_data[MAX_CONN];
		ConnectionProcessor *pProcessor = static_cast<ConnectionProcessor *>(this);
		while (breakbool)
		{
			nConnectedSocket = ::accept(nListenSocket, (sockaddr *)&ClientAddress, &LengthOfClientAddress);
			if (-1 == nConnectedSocket)
			{
				std::cout << "accept error" << std::endl;
				::close(nListenSocket);
				return -1;
			}
			std::cout << "accept success" << std::endl;	
			Thread_data temp;
			temp.nConnectedSocket = nConnectedSocket;
			temp.server = pProcessor;
			memcpy(&thread_data[i],&temp,sizeof(temp));
			// 多线程处理client
			pthread_create(&tid, NULL,serverFun,(void*)&thread_data[i++]);
			pthread_detach(tid);
			// pProcessor->ServerFunction(nConnectedSocket, nListenSocket, &breakbool);
			std::cout << "serverfunction success" << std::endl;
			if(i>=MAX_CONN)  //如果连接数过多，就不再接收连接请求了
			{
				cout<<"Reach the max connections : "<<strerror(errno)<<endl;
				break;
			}
		}

		::close(nConnectedSocket);
		::close(nListenSocket);

		return 0;
	}

private:
	int m_nServerPort;
	char *m_strBoundIP;
	int m_nLengthOfQueueOfListen;
};

class CMyTCPServer
{
public:
	CMyTCPServer()
	{}

	virtual ~CMyTCPServer()
	{
		pluginController.UninitializeController();
	}

	void initFunction(string serverName)
	{
		std::cout << "服务器初始化" << std::endl;
		pluginController.InitializeController(serverName);
		pluginController.getPlugins(&pluginList);
		std::cout << "初始化时插件数目：" << pluginList.size() << std::endl;
	}

	// 减少库存
	bool decreaseByGoodsId(int goosId, int count)
	{

		if (count < 0){
			std::cout << "输入有误" << std::endl;
			return false;
		}
		for (int i = 0; i < pluginList.size(); i++)
		{
			if (goosId == pluginList[i]->m_id)
			{
				if (count > pluginList[i]->m_stock)
				{
					std::cout << "库存不足" << std::endl;
					return false;
				}
				pluginList[i]->m_stock -= count;
				return true;
			}
		}
		std::cout << "商品id有误" << std::endl;
		return false;
	}

	void showItems()
	{
		cout << "仓库信息：" << endl;
		printf("商品id\t商品名称\t单价\t库存数量\n");
		for (int i = 0; i < pluginList.size(); i++)
		{
			pluginList[i]->PrintInfo();
		}
	}

	void serverSerialize()
	{
		cout << "开始序列化" << endl;
		
		pluginController.ProcessSerialize(m_serverId);
	}

	// TODO 反序列化的逻辑写的和屎一样，累了，后面再改
	void serverDeserialize()
	{
		if (m_serverId == 1){
			pluginController.InitializeController("B");
		}else if (m_serverId == 2){	
			pluginController.InitializeController("A");
		}
		std::vector<IGoodsPlugin *> AvpPlugins;
		pluginController.getPlugins(&AvpPlugins);
		for(int i=0; i<AvpPlugins.size(); i++)
		{
			pluginList.push_back(AvpPlugins[i]);
		}
		pluginController.setPlugins(&pluginList);
		pluginController.ProcessDeserialize(m_serverId);
	}

	void sendItemsMsg(int nConnectedSocket)
	{
		char buf[100];
		int usedIndex = 0;
		string msg;
		for (int i = 0; i < pluginList.size(); i++)
		{
			string itemName = pluginList[i]->m_name;

			msg += std::to_string(pluginList[i]->m_id) + ' ' + itemName + ' ' + std::to_string(pluginList[i]->m_price) + ' ';
			// std::cout << msg << std::endl;
		}
		strcpy(buf, msg.c_str());
		sendMessageStr(nConnectedSocket, buf, 100);
	}

	// 检查商品库存是否足够
	void isGoodStock(int nConnectedSocket)
	{
		char buf[100];
		// 想不到好办法呀
		::write(nConnectedSocket, buf, 100); //为了检测有没有socket断连接

		::read(nConnectedSocket, buf, 100);
		string str = buf;
		string out;
		stringstream istr(str);
		istr >> out;
		int user_id = std::stoi(out);
		istr >> out;
		int goods_id = std::stoi(out);
		istr >> out;
		int num = std::stoi(out);

		if (!decreaseByGoodsId(goods_id, num))
		{	
			// 如果不成功
			sendMessageInt(nConnectedSocket, -1);
		}else
		{
			sendMessageInt(nConnectedSocket, 1);
			cout << "返回购买完成，库存足够" << endl;
		}
	}

	bool requireMessageInt(int nConnectedSocket, int *msg, int *user_id)
	{
		char buf[100];
		::read(nConnectedSocket, buf, 100);
		//std::cout << atoi(buf) << std::endl;
		string strBuf = buf;
		string out;
		stringstream istrBuf(strBuf);
		
		try
		{
			istrBuf >> out;
			*user_id = std::stoi(out);
			istrBuf >> out;
			*msg = std::stoi(out);
			m_userId.push_back(*user_id);
			cout << "处理业务" << *msg << endl;
			return true;
		}catch(const std::exception& e)
		{
			std::cerr << e.what() << '\n';
			return false;
		}
		
		
	}

	void sendMessageStr(int nConnectedSocket, char *buf, int len)
	{
		::write(nConnectedSocket, buf, len);
	}

	void sendMessageInt(int nConnectedSocket, int msg)
	{
		char buf[100];
		sprintf(buf, "%d", msg);
		::write(nConnectedSocket, buf, 100);
	}



public:
	// 用户id
	vector<int> m_userId;
	// 插件控制器
	CPluginController pluginController;
	// 插件列表
	std::vector<IGoodsPlugin *> pluginList;
	// 商品列表
	vector<int> goodsId;
	// 服务器id
	int m_serverId;
	
	int allPluginNum = 4;

	friend void *serverFun( void* arg );
};

// 业务逻辑代码
void* serverFun( void* arg )
{
   	/* 因为 serverFun() 是 Box 的友元，它可以直接访问该类的任何成员 */
   	Thread_data *thread_data = (Thread_data *)arg;
  	CMyTCPServer* server = thread_data->server;
	int nConnectedSocket = thread_data->nConnectedSocket;	
	std::cout << "server : "<<server->m_serverId << " nConnectedSocket : "<<nConnectedSocket<<std::endl;
	// 宕机点
	bool breakbool2 = true;
	while (breakbool2)
	{
		// caseNum
		int caseNum;
		int user_id;
		bool flag = server->requireMessageInt(thread_data->nConnectedSocket, &caseNum, &user_id);
		cout<<"user_id:"<<user_id<<"的消息"<<endl;
		if (!flag) {
			cout<<"客户端ctrl c处理，防止程序崩溃"<<endl;
			caseNum = 3;
			// break;
		}
		switch (caseNum)
		{
			// 辅助客户端初始化业务
			case 0:
				// 发送到客户端，所有商品的id，name, price
				server->sendItemsMsg(nConnectedSocket);
				server->showItems();
				break;
			// 购买商品，buf="id n" 第id号商品，买n个。
			case 1: 
				// 检查库存是否足够
				server->isGoodStock(nConnectedSocket);
				server->showItems();
				// 每次商品库存减少，做序列化操作，覆盖文件。
				// if (server->m_serverId == 1)
				server->serverSerialize();
				break;
			// 客户端退出，结束线程
			case 3:
				breakbool2 = false;
				break;
			case 4:
				// 序列化操作
				// server->serverDeserialize();
				// server->showItems();
					//sendItemsMsg(nConnectedSocket);
				break;
			case 5:
				// 反序列化操作
				if (server->pluginList.size() < 4){
					server->serverDeserialize();
				}
				server->showItems();
				server->sendItemsMsg(nConnectedSocket);
				break;
			case 6:
				//  模拟宕机用
				// 	breakbool2 = false;
			
				break;
			// 测试
			case 7: 
				string strMsg = "用户:" + to_string(user_id) + "服务" + to_string(thread_data->server->m_serverId);
				char buf[100];
				strcpy(buf, strMsg.c_str());
				thread_data->server->sendMessageStr(thread_data->nConnectedSocket, buf, 100);
				// thread_data->server->sendMessageInt(thread_data->nConnectedSocket,thread_data->server->m_serverId);
				break;
		}	
	}
	cout <<"客户端退出了"<<endl;
}


int main(int argc, char **argv)
{
	std::cout << "enter main " << std::endl;
	if (argc == 2)
	{
		if (strcmp(argv[1], "A") == 0)
		{
			std::cout << "Server A run " << std::endl;
			CTCPServer<CMyTCPServer> myserver(4000);
			myserver.m_serverId = 1;
			myserver.initFunction("A");
			std::cout << "init CTCPServer success" << std::endl;
			myserver.Run();
		}
		else if (strcmp(argv[1], "B") == 0)
		{
			std::cout << "Server B run" << std::endl;
			CTCPServer<CMyTCPServer> myserver(5000);
			myserver.m_serverId = 2;
			myserver.initFunction("B");
			std::cout << "init CTCPServer success" << std::endl;
			myserver.Run();
		}
	}
	return 0;
}
